/*
 * @Author: xiaosihan 
 * @Date: 2024-05-25 13:11:35 
 * @Last Modified by: xiaosihan
 * @Last Modified time: 2024-05-29 04:35:33
 */

import homeStore from "@views/home/homeStore";
import { autorun } from "mobx";
import { DoubleSide, Group, Mesh, MeshBasicMaterial, MeshLambertMaterial, MeshStandardMaterial, SRGBColorSpace, Vector3 } from "three";
import threeLoader from "three-base/threeLoader";
import GeojsonLine from "../GeojsonLine";
import GeojsonMesh from "../GeojsonMesh";
import FlyLineFocusGroup from "./FlyLineFocusGroup/FlyLineFocusGroup";
import FlyLineGroup from "./FlyLineGroup/FlyLineGroup";
import beijingJSON from "./beijing.json";
import sidePNG from "./side.png";
import BarGroup from "./BarGroup/BarGroup";
import ScatterGroup from "./ScatterGroup/ScatterGroup";
import InfoPointGroup from "./InfoPoint/InfoPoint";
import Transition from "three-base/Transition";

// 北京地图
export default class BeijingMap extends Group {
    constructor() {
        super();
    }

    // 初始动画
    async init() {
        await this.transition.reset({ scaleY: 0.01 });
        await this.transition.set({ scaleY: 1 });
    }

    transition = (() => {
        const transition = new Transition({ scaleY: 0.01 });
        transition.setBezier([0, 0, 1, 1]);
        transition.setDuration(1000);
        transition.onChange(({ scaleY }) => {
            this.scale.set(1, scaleY, 1);
            this.position.set(0, 0, (scaleY > 0.01 ? 0 : 9999));
        });
        return transition;
    })();

    // normalMaterial
    normalMaterial = new MeshLambertMaterial({
        color: "#36898b",
        transparent: true,
        opacity: 0.5,
    });

    //activeMaterial
    activeMaterial = new MeshBasicMaterial({
        // activeMaterial = new MeshLambertMaterial({
        color: "#ffffff",
        transparent: true,
        opacity: 0.5,
    });

    sideMap = (() => {
        const sideMap = threeLoader.getTexture(sidePNG);
        sideMap.colorSpace = SRGBColorSpace;
        return sideMap;
    })();

    //sideMaterial
    sideMaterial = (() => {
        const sideMaterial = new MeshStandardMaterial({
            color: "#49c0c5",
            map: this.sideMap,
            fog: false,
            opacity: 1,
            side: DoubleSide,
        });
        return sideMaterial;
    })();

    //地图偏移量
    offset = new Vector3(-116.468994140625 * 5, 0.01, 40.25177764892578 * 5);

    //北京轮廓线
    beijingLine = (() => {
        const scale = 5;
        const beijingLine = new GeojsonLine(beijingJSON);
        beijingLine.scale.set(scale, scale, scale);
        beijingLine.position.set(-116.468994140625 * scale, 0.511, 40.25177764892578 * scale);
        this.add(beijingLine);
        return beijingLine;
    })();

    //北京模型
    beijingMesh = (() => {
        const scale = 5;
        const beijingMesh = new GeojsonMesh(beijingJSON, 0.1);
        beijingMesh.bottomGroup.traverse(obj => {
            if ((obj as Mesh).isMesh) {
                (obj as Mesh).material = new MeshBasicMaterial({
                    color: "#379195",
                    transparent: true,
                    opacity: 1,
                })
            }
        })

        //
        beijingMesh.sideGroup.traverse(obj => {
            if ((obj as Mesh).isMesh) {
                (obj as Mesh).material = this.sideMaterial;
            }
        });

        beijingMesh.topGroup.traverse(obj => {
            if ((obj as Mesh).isMesh) {
                Object.assign(obj.userData, {
                    cursor: "pointer",
                    enableEvent: true,
                });
                //three事件
                obj.addEventListener("click", (e: any) => {
                    const { name, code } = (obj as Mesh).userData;
                    console.log("click", name, code);
                    const offset = new Vector3(-116.468994140625 * 5, 0, 40.25177764892578 * 5);
                    const p = e.point.sub(offset).divideScalar(5);
                    debugger;
                    console.log(JSON.stringify({ "lng": p.x, "lat": -p.z }));
                });
                obj.addEventListener("mouseenter", e => {
                    const { code } = (obj as Mesh).userData;
                    homeStore.setHoverAreaCode(code);
                });
                obj.addEventListener("mouseleave", e => {
                    homeStore.setHoverAreaCode("");
                });
            }
        });

        beijingMesh.scale.set(scale, scale, scale);
        beijingMesh.position.set(-116.468994140625 * scale, 0.01, 40.25177764892578 * scale);
        this.add(beijingMesh);
        return beijingMesh;
    })();

    //飞线分组
    flyLineGroup = (() => {
        const flyLineGroup = new FlyLineGroup();
        this.add(flyLineGroup);
        return flyLineGroup;
    })();

    //飞线焦点分组
    flyLineFocusGroup = (() => {
        const flyLineFocusGroup = new FlyLineFocusGroup();
        flyLineFocusGroup.visible = false;
        this.add(flyLineFocusGroup);
        return flyLineFocusGroup;
    })();

    //柱状图组
    barGroup = (() => {
        const barGroup = new BarGroup();
        this.add(barGroup);
        return barGroup;
    })();

    //散点组
    scatterGroup = (() => {
        const scatterGroup = new ScatterGroup();
        this.add(scatterGroup);
        return scatterGroup;
    })();

    //信息弹窗
    infoPointGroup = (() => {
        const infoPointGroup = new InfoPointGroup();
        this.add(infoPointGroup);
        return infoPointGroup;
    })();

    dispose = autorun(() => {
        const { hoverAreaCode } = homeStore;
        this.beijingMesh.topGroup.traverse(obj => {
            if ((obj as Mesh).isMesh) {
                const { code } = (obj as Mesh).userData;
                (obj as Mesh).material = [hoverAreaCode, ""].includes(code) ? this.activeMaterial : this.normalMaterial;
            }
        });
    });

    dispose1 = autorun(() => {
        const { showFlyLine, showScatter, showPoint } = homeStore;
        this.flyLineGroup.visible = showFlyLine;
        this.scatterGroup.visible = showScatter;
        this.infoPointGroup.visible = showPoint;
    });

    updateMatrixWorld(force?: boolean | undefined): void {
        this.sideMap.offset.y += 0.01;
        super.updateMatrixWorld(force);
    }

}